import hook from '@/hooks/cloud/onUnmounuuid'
import { typeOf, getNowDate } from '@/utils/cloud/utils'
import { lastFormatt } from '@/utils/cloud/sqlQuery'
import { danweiHs } from '@/components/GoCustomChart/config'
import PreviewAPI from '@/api/preview'
import { isEdge } from '@/utils'

let timerHash = {}
export default () => {
  const { getUUID, store, clear } = hook()

  // 查询多设备分时段计量汇总
  const getActivePowerSumByTime = async config => {
    return new Promise(async (resolve, reject) => {
      let {
        subtotal_name,
        type,
        start_time,
        end_time,
        siteId,
        time,
        iot,
        component_ids,
        format,
        table = '',
        attr = ['active_power'],
        operator,
        outer_aggregate = 'sum',
        inner_aggregate = 'avg',
        inner_aggregate1,
        inner_aggregate_content,
        outer_aggregate_content,
        need_socket = false,
        callback,
        fillType = 'previous',
        filter_conditions,
        UUID
      } = config
      let iotArray
      if (iot) {
        //默认不传iot则自动请求计量设备的iot_id，如果传了则用传的
        iotArray = iot
      } else {
        // const iot_idObject = await getsiteIot(siteId, hash[type].energyType) //查询计量设备的iot_id
        // iotArray = iot_idObject[`${hash[type].metersType}Meters`]
      }
      // let methods = format ? format : 'tsdbSearch'
      if (iotArray.length === 0) {
        resolve(
          format === 'tsdbSearchseries'
            ? {
                data: {},
                iotId: ''
              }
            : {
                data: [],
                iotId: ''
              }
        )
        return
      }
      if (!time || typeOf(time) === 'number') {
        time = time ? `${time}s` : '60s'
      }
      UUID = UUID || getUUID()
      store.getSocket.then(async socket => {
        filter_conditions = filter_conditions || true
        let query = {
          application: 'linku_ems',
          datasource: 'ems_tsdb',
          name: 'energy_subsystem_statistic_by_time_window',
          format: format === 'tsdbSearchseries' ? 'series' : 'dict',
          param: {
            subtotal_name: subtotal_name || type,
            outer_aggregate: attr
              .map(item => {
                if (outer_aggregate_content) return outer_aggregate_content
                return outer_aggregate + '(`' + item + '`)' + `${operator ? operator : ''} ` + '`' + item + '`'
              })
              .join(','),
            inner_aggregate: attr
              .map(item => {
                if (inner_aggregate_content) return inner_aggregate_content
                if (inner_aggregate1) {
                  return inner_aggregate + '(' + inner_aggregate1 + '(`' + item + '`)) ' + '`' + item + '`'
                }
                return inner_aggregate + '(`' + item + '`) ' + '`' + item + '`'
              })
              .join(','),
            table,
            date: [start_time, end_time],
            startDateTime: start_time,
            endDateTime: end_time,
            iot_id: iotArray.flat().join("','"),
            time,
            fillType,
            filter_conditions
          },
          noPush: !need_socket,
          websocket_config: {
            endtime: end_time,
            format: format === 'tsdbSearchseries' ? 'series' : 'dict',
            register: attr.map(item => {
              return {
                channel: item,
                aggregate: inner_aggregate,
                group_aggregate: outer_aggregate,
                iot_id: iotArray.flat().join(','),
                register_id: item
              }
            })
          }
        }
        if (query.param.inner_aggregate.includes('delta')) {
          query.name = 'energy_subsystem_statistic_by_time_window_delta'
        }

        if (isEdge()) {
          const res = await PreviewAPI.getDatapoolTsdb(
            {
              ...query.param,
              component_ids
            },
            'energy_subsystem_statistic_by_time_window'
          )
          let result = {
            data: res.msg || [],
            iotId: iotArray.flat().join("','"),
            msg_type: 'query'
          }
          resolve(result)
          return
        }
        socket.send(query, UUID, res => {
          if (res.code !== 200 || res.msg_type === 'timeout') return
          if (need_socket && res.msg_type === 'query' && res.msg && res.msg.length) {
            // if (!end_time || (end_time && new Date(end_time) >= new Date(res.msg[res.msg.length - 1].time))) {
            //   res.msg.pop()
            // }
          }
          let result = {
            data: res.msg || [],
            iotId: iotArray.flat().join("','"),
            msg_type: res.msg_type
          }
          if (callback && res.msg_type === 'instant') callback(result)
          if (res.msg_type === 'query') resolve(result)
        })
      })
    })
  }

  const getDeviceProperties = async (param, callback) => {
    let { aggregate, attrs, needtime, neediotid, dict, date, table, component_ids, timerId } = param
    if (!param.iot_id) return
    let datas = {
      channel: [], //所有channel
      channel_category: [],
      category: {}, //最终要传入的
      resData: {}
    }
    let UUID
    let UUIDList = []
    if (typeOf(param.iot_id) === 'string') {
      param.iot_id = [param.iot_id]
    }
    if (!dict) {
      const res = await PreviewAPI.getDictionary(param.iot_id[0], 'iot_id')
      if (res.code == 200) {
        //获取当前的设备UI模型
        datas.resData = res.msg
      }
    } else {
      datas.resData = dict
    }
    let condition_channels = []
    //如果传入uimodel，查找到所有引用的channel
    if (param.ui_model && datas.resData.ui[param.ui_model]) {
      let UI_model = datas.resData.ui[param.ui_model].default
      UI_model.forEach(item => {
        datas.channel.push(item.channel)
        if (item.conditions) {
          const getChannels = c => {
            if (typeOf(c) === 'object') {
              for (let key in c) {
                if (key === 'channel' && c[key]) {
                  condition_channels.push(c[key])
                } else if (typeOf(c[key]) === 'object' || typeOf(c[key]) === 'array') {
                  getChannels(c[key])
                }
              }
            } else if (typeOf(c) === 'array') {
              c.forEach(item => {
                getChannels(item)
              })
            }
          }
        }
      })
      datas.channel = datas.channel.concat(
        UI_model.map(item => {
          return item.channel
        })
      )
    }
    if (datas.channel.length === 0 && param.channel) {
      datas.channel = datas.channel.concat(param.channel)
    }
    if (param.attrs) {
      datas.channel = datas.channel.concat(param.attrs)
    }

    condition_channels = condition_channels.filter(item => {
      return datas.channel.indexOf(item) < 0
    })
    // if (datas.channel.length === 0) {
    //   datas.channel = datas.channel.concat(Object.keys(datas.resData.key_dict))
    // }
    datas.channel = datas.channel.concat(condition_channels)
    if (datas.channel.length) {
      for (let key in datas.resData.channel_category) {
        datas.channel.concat(condition_channels).forEach((item, index) => {
          if (datas.resData.channel_category[key].indexOf(item) >= 0) {
            datas.category[key] ? datas.category[key].push(item) : (datas.category[key] = [item])
          }
        })
      }
    }
    //这个处理的分类信息详情，比如告警和简要等等集合全部
    else if (param.category) {
      //如果传入了channel,则直接使用channel
      datas.category = param.category
    } else {
      if (param.channel_category) {
        //如果用户传入了channer_category子项(分类：例如：measurement),
        //如果用户传入了channel_category
        datas.category[param.channel_category] = datas.resData.channel_category[param.channel_category].filter(item => {
          return datas.channel.includes(item)
        })
      } else {
        for (let i in datas.resData.channel_category) {
          let categoryData = datas.resData.channel_category[i].filter(item => {
            return datas.channel.includes(item)
          })
          if (categoryData.length) {
            datas.category[i] = categoryData
          }
        }
      }
    }
    store.getSocket.then(async socket => {
      if (UUID) {
        socket.onUnmoun(UUIDList.filter(item => item.indexOf(UUID) >= 0))
      }
      UUID = getUUID()

      for (let sq in datas.category) {
        let query = {
          application: 'linku_ems',
          datasource: 'ems_tsdb',
          name: 'general_instant_query',
          param: {
            lastvalue: datas.category[sq],
            table: table || `${datas.resData.product_category}_${sq}`,
            iot_id: param.iot_id.join("','"),
            component_ids: component_ids
            // aggregate: aggregate,
          }
        }
        if (date) {
          query.param.date = date
        } else {
          let start = format(new Date(getNowDate().getTime() - 10 * 60 * 1000), 'yyyy-MM-dd HH:mm:ss')
          if (sq === 'alert' || sq === 'state') {
            start = format(new Date(getNowDate().getTime() - 7 * 24 * 60 * 60 * 1000), 'yyyy-MM-dd HH:mm:ss')
          }
          query.param.date = [start, format(getNowDate(), 'yyyy-MM-dd 23:59:59')]
        }

        UUIDList.push(UUID + sq)

        let getFinalData = resData => {
          let data = {}
          Object.keys(resData).forEach(item => {
            if (needtime) {
              data.time = resData.time
            }
            if (neediotid) {
              data.iot_id = resData.iot_id
            }

            if (!['iot_id', 'time'].includes(item)) {
              let resValue = resData[item]
              if (Array.isArray(resValue)) {
                resValue = resValue.filter(val => val !== null)
                if (resValue.length) {
                  if (aggregate === 'sum') {
                    resValue = resValue.reduce((total, current) => {
                      return total + current
                    }, 0)
                  } else if (aggregate === 'avg') {
                    resValue =
                      resValue.reduce((total, current) => {
                        return total + current
                      }, 0) / resData[item].length
                  } else {
                    resValue = resValue.reverse().find(el => el || el === 0)
                  }
                } else {
                  resValue = ''
                }
              }
              data[item] = {
                value: getDescValue(item, resValue, datas.resData.unit_dict[item.toUpperCase()], datas.resData).value,
                label: datas.resData.key_dict[item.toUpperCase()],
                unit: getDescValue(item, resValue, datas.resData.unit_dict[item.toUpperCase()], datas.resData).unit,
                oldValue: resValue,
                oldUnit: datas.resData.unit_dict[item.toUpperCase()],

                show: !condition_channels.includes(item)
              }
            }
          })
          data.ui_model = datas.resData.ui[param.ui_model]
          return data
        }

        if (isEdge()) {
          const getChannelData = async () => {
            const res = await PreviewAPI.getDatapoolTsdb(
              {
                inner_aggregate: lastFormatt([...new Set(query.param.lastvalue)]),
                iot_id: query.param.iot_id,
                component_ids: query.param.component_ids,
                startDateTime: query.param.date[0],
                endDateTime: query.param.date[1]
              },
              'general_instant_query'
            )
            let data
            if (res.msg && res.msg.iot_id) {
              data = res.msg.iot_id.map((item, index) => {
                let obj = {}
                for (let key in res.msg) {
                  obj[key] = res.msg[key][index]
                }
                return {
                  ...getFinalData(obj)
                }
              })

              callback(data, res.msg)
            }
          }
          getChannelData()
          let timer = setInterval(() => {
            getChannelData()
          }, 60 * 1000)
          timerHash[timerId] = timer
        } else {
          socket.send(query, UUID + sq, res => {
            if (res.code !== 200 || res.msg_type === 'timeout') return
            let data
            if (param.iot_id.length !== 1 && typeOf(res.msg.iot_id) === 'array' && aggregate === 'every') {
              data = res.msg.iot_id.map((item, index) => {
                let obj = {}
                for (let key in res.msg) {
                  obj[key] = res.msg[key][index]
                }
                return {
                  ...getFinalData(obj)
                }
              })
            } else {
              data = getFinalData(res.msg)
            }
            callback(data, res.msg)
            // socket.send({ session_id: res.session_id })
          })
        }
      }
    })
  }

  const getDescValue = (key, data, unit, datas) => {
    let hash = datas.enum_dict
    let ObjectData = {}
    let hashValue = hash[key.toLocaleUpperCase()] ? hash[key.toLocaleUpperCase()][data] : null
    if (hashValue) {
      ObjectData = {
        unit: unit,
        value: hashValue
      }
    } else {
      let value = danweiHs(data, unit, data)
      ObjectData = {
        unit: value.unit,
        value: value.val || value.val === 0 ? (value.val * 1).toFixed(2) : '--'
      }
    }
    return ObjectData
  }

  const clearSocket = () => {
    clear()
  }

  const clearTimer = list => {
    list.forEach(item => {
      if (timerHash[item]) {
        clearInterval(timerHash[item])
        delete timerHash[item]
      }
    })
  }

  return {
    getActivePowerSumByTime, //分时段查询计量数据
    getDeviceProperties,
    clearSocket,
    clear: clearSocket,
    clearTimer
  }
}
